import requests
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import xlwt
import jieba
from collections import Counter
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from operator import itemgetter
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def get_one_page(url):
    headers = {
        'authority': 's.taobao.com',
        'method': 'GET',
        'path': '/api?_ksTS=1507342673846_219&callback=jsonp220&ajax=true&m=customized&sourceId=tb.index&_input_charset=utf-8&bcoffset=0&commend=all&suggest=history_3&source=suggest&search_type=item&ssid=s5-e&suggest_query=&spm=a21bo.50862.201856-taobao-item.2&q=%E7%94%B7%E8%A3%A4&s=36&initiative_id=tbindexz_20171007&imgfile=&wq=&ie=utf8&rn=cfb3eea8ae196efafa5f813ae2df21f0',
        'scheme': 'https',
        'accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01',
        'accept-encoding': 'gzip, deflate, sdch, br',
        'accept-language': 'zh-CN,zh;q=0.8',
        'cookie': 'miid=1504824888974818073; UM_distinctid=15e237dee84f7-010596f6e-4349072c-100200-15e237dee861; __guid=154677242.4031585706812497000.1503836519346.7197; hng=CN%7Czh-CN%7CCNY%7C156; thw=cn; uc3=sg2=UoTfKLITZlXL0Is5hM5B8XwcEuTdKWFDpygC46JxjmY%3D&nk2=CcYx2hamYD8%3D&id2=UUtO8RnzigwHKQ%3D%3D&vt3=F8dBzWk433CNuDrC6fk%3D&lg2=V32FPkk%2Fw0dUvg%3D%3D; uss=AQGnxugLA99LFC3dRcR7YtJLXj1y8oHxZ6CNxGyZOT6uM3NzUAGT0EoogA%3D%3D; lgc=justijin; tracknick=justijin; mt=np=&ci=5_1; _cc_=W5iHLLyFfA%3D%3D; tg=0; t=2010491725ba88cebe30bf46b3adf8c7; cookie2=610d7a48bb9c6016eb4fd9788b3b5f74; v=0; _tb_token_=e97f14ee5be5e; alitrackid=www.taobao.com; lastalitrackid=www.taobao.com; JSESSIONID=1A74F2E4738351A204F0CACF5D2DC712; isg=AhkZNMCmpFBeBXhSjyEkH3TyKAVftEV_wW-KEzvOVsC8QjnUg_YdKIcSMAnX; monitor_count=18; cna=uwjEEXc6M3kCAd9KMy5L8J5W',
        'referer': 'https://s.taobao.com/search?initiative_id=tbindexz_20171007&ie=utf8&spm=a21bo.50862.201856-taobao-item.2&sourceId=tb.index&search_type=item&ssid=s5-e&commend=all&imgfile=&q=%E7%94%B7%E8%A3%A4&suggest=history_3&_input_charset=utf-8&wq=&suggest_query=&source=suggest',
        'user-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
        'x-requested-with': 'XMLHttpRequest'
    }

    try:
        response=requests.get(url, headers=headers)
        if response.status_code==200:
            return  response.text
        return None
    except RecursionError:
        return None

def get_information(urls):
    a = 0
    c = []
    for url in urls:
        html= get_one_page(url)
        s = '"raw_title":"(.+?)","pic_url".+?"view_price":"(.+?)","view_fee".+?' \
            '"item_loc":"(.+?)","view_sales":' \
            '"(.+?)人付款","comment_count".+?"nick":"(.+?)","shopcard"'
        items = re.compile(s, re.S).findall(html)
        c.append(items)
        a += 1
        print('爬取第%d页' % a)
    return c

def write_to_file(content,a):
    d=str(a)+'信息.txt'
    print(d)
    with open(d,'a',encoding='utf-8')as f:
        for i in content:
            f.write(str(i) + '\n')
    f.close()
    print('写入TXT成功')

def save_to_Excel(items,a):
    #print(len(items))
    ws = xlwt.Workbook()
    w = ws.add_sheet('抓取的信息.xls', cell_overwrite_ok=True)
    sa = ["商品位置", "商品名称", "商品价格", "商品产地", "月销量", "商店名称"]
    for c in range(0, len(sa)):
        w.write(0, c, sa[c])
    n=i= 0
    for d in range(len(items)*44-8):
        n += 1
        w.write(d+1,0,n)

    def ji(i):    #累加函数
        return i + 1
    for item in items:
        for it in item :

            i=ji(i)
            #print(i)
            for j in range(len(it)):
                w.write(i,j+1,it[j])

    #print('写入Excel成功')
    ws.save('抓取的信息.xls')

def urlsd(a,b,c):
    
    urls = []
    for i in range(int(b)):
        urls.append( 'https://s.taobao.com/search?q=' + str(a) + '&bcoffset=4&ntoffset=4&p4ppushleft=1%2C48&s='+str(i*44))
    #print(urls)
    ab= get_information(urls)
    #print(len(ab))
    if c=='Excel表格':
        save_to_Excel(ab,a)
    else:
        save_to_Excel(ab,a)
        write_to_file(ab, a)

def excel_pattern()  :
    '''淘宝商家的省份分析
            中国有34个省，建立一个省份和零元素对应的列表，
            从列表中取出省份，用正则表达式匹配从表格中提取的商品产地，
            匹配到哪个省列表对应那个省份数值加1，统计出
            每个省出现的数量，再对列表进行排序，如果某个省份
            出现的数量大于0，则将省份和数值分别放入另外两个表
            a，b作为列变量和行变量，为了图的美观，如果列变量a多于20个
            ，清空a，b，再把数值大于爬取的个数总量的1%的省份放入a，b，
            最后画图
         '''
    data=pd. read_excel('抓取的信息.xls')
    provinces=[ ['辽宁',0],['吉林',0],['黑龙江',0],['海南',0],['贵州',0],['云南',0],['陕西',0],
                ['甘肃',0],['广西',0],['西藏',0],['宁夏',0],['新疆',0],['香港',0],['青海',0],
                ['台湾',0],['内蒙古',0],['澳门',0],['重庆',0],['湖南',0], ['山西',0],[ '安徽',0],
                [ '江西',0] ,['河南',0], ['湖北',0],['四川',0],['天津',0],['河北',0],['山东',0],
                ['北京',0], ['上海',0], ['江苏',0], ['福建',0], ['浙江',0],[ '广东',0]]
    d=[]
    e=[]
    for i in range(len(data)):
        item=data[ '商品产地'][i]
        for place in provinces:
            c1 = re.compile(place[0]).findall(str(item))
            if c1!=[]:
                place[1]+=1
    provinces=sorted(provinces,key=itemgetter(1))
    #print(provinces)
    for place in provinces:
        if place[1]>0:
            e.append(place[1])
            d.append(place[0])
    if len(e)>20:
        e=[]
        d=[]
        for place in provinces:
            if place[1] >len(data)*0.01:
                e.append(place[1])
                d.append(place[0])
    index =np. arange(1,len(e)+1)
    plt.barh(index, e)
    plt.title('淘宝商家的省份分布')
    plt.yticks(index+0.1, d)
    plt.show()


def picher():
    '''#商店名称饼型图
    商店名称一般有旗舰店、专营店、专卖店和其他，
    从表格提取出每一个商店名称，用正则表达式匹配，
    确定其属于哪一类，再画图
    '''
    data = pd.read_excel('抓取的信息.xls')
    shop_names=['旗舰店','专营店','专卖店','其他']
    c = np.zeros(4)
    cs=len(data)
    for i in range(cs):
        item = data['商店名称'][i]
        j = 0
        for name in shop_names:
            j += 1
            re_name='.+?'+name
            c1 = re.compile(re_name).findall(str(item))
            if c1 != []:
                c[j - 1] += 1
                data=data.drop(i)
            else:
                continue
    c[-1]=len(data)
    for n in range(len(shop_names)):
        ds = c[n]/cs*100
        shop_names[n]=shop_names[n]+'%d%%'%ds
    colors=['blue','green','red','yellow']
    plt.title('淘宝商店名比例')
    plt.pie(c,labels=shop_names,colors=colors)
    plt.axis('equal')
    plt.show()

#picher()

def tiao():
    '''#制作价格区间水平条状图
    从表格提取数据，清洗缺失值，并写入新列表，
    因商品的价格分布跟数量分布跨度都很大，用一般的等价格区间画图
    会造成某一区间数量很多，而另外几个区间没有数据，所以本函数先确定
    商品价格的最高值、最低值和中位数，以中位数为中点，向左右各分五个区间
    统计其中分布数量，最后画图。
    '''
    data = pd.read_excel('抓取的信息.xls')
    c = np.zeros(10)
    g=[]
    for i in range(len(data)):  #清洗缺失值
        if data['商品价格'][i].astype('int') !=-2147483648:
            g.append(data['商品价格'][i])
    a=max(g)
    d = min(g)
    b= np.median(g)   #中位数
    #print(a,b,d)
    s = int((b-d)/5)
    s1 = int((a-b)/5)
    #print(s,s1)
    for i in range(len(g)):
        item=g[i]
        if item <= d + s:
            c[9] += 1
        elif item <=d + s*2:
            c[8]+= 1
        elif  item <=d + s*3:
            c[7] += 1
        elif  item <=d + s*4:
            c[6] += 1
        elif  item <=d + s*5:
            c[5] += 1
        elif item <=b + s1:
            c[4] += 1
        elif item <b + s1*2:
            c[3] += 1
        elif item <b + s1*3:
            c[2] += 1
        elif item <b + s1*4:
            c[1] += 1
        else:
            c[0] += 1
    index = [1, 2, 3, 4, 5, 6,7,8,9,10]
    #print(c)
    plt.barh(index, c)
    plt.title('淘宝商品价格区间')
    sd=[]
    for i in range(5):
        sd.append('%d元到%d元'%(d + s*i,d + s*(i+1)))
        #print(s*i)
    sd.append('%d元到%d元'%(d + s*5,b +s1))
    for i in range(2,6):
        sd.append('%d元到%d元' % ( b + s1* (i-1) , b + s1 * i))
    plt.yticks(index,sd )
    plt.show()
#tiao()
def tiaop():
    '''
    提取表格中的月销量，按顺序画图，
    代表每个商品的月销量跟它在淘宝中的位置的关系
    '''
    data = pd.read_excel('抓取的信息.xls')
    g = []
    for i in range(len(data)):  # 清洗缺失值
        if data['月销量'][i].astype('int') != -2147483648:
            g.append(data['月销量'][i])
    x1 = np.arange(len(g))
    y1 = g
    plt.title('销量与商品位置的关系')
    plt.ylabel('销量')
    plt.xlabel('位置')
    plt.plot(x1, y1)
    plt.show()

#tiaop()

def merchandise_name():
    '''淘宝商品名分析
    先从表格当中把所以商品名称提取出来，写入TXT文件，
    用结巴分词（jieba）把TXT文件中的词全部分开，
    用Counter统计每个词在文本中的数量，生成（key，k）这样的元祖，
    key为词，作为图的列，k为数量，作图。
    '''
    data=pd. read_excel('抓取的信息.xls')
    with open('a.txt', 'w', encoding='utf-8')as f:
        for i in range(len(data)):
            item=data[ '商品名称'][i]
            f.write(str(item)+'\n')
    f.close()
    key=[]
    k=[]
    with open('a.txt',encoding='utf-8')as f2:
        d = f2.read()
        santi_words = [x for x in jieba.cut(d) if len(x) >= 2]
        c = Counter(santi_words).most_common(20)
        for i in range(len(c)):
            key.append(c[i][0])
            k.append(c[i][1])
    index =np.arange(1,21)
    key=key[::-1]
    k=k[::-1]
    plt.barh(index, k)
    plt.title('商品名筛选条件')
    plt.yticks(index+0.1, key)
    plt.show()



def main():
    root = Tk()
    root.title('淘宝信息提取分析小程序')
    tabControl = ttk.Notebook(root)         #创建主窗口
    tab1 = ttk.Frame(tabControl)            # 添加分页窗口1
    tabControl.add(tab1, text='爬虫')      # 分页窗口1名称
    tab2 = ttk.Frame(tabControl)            # 添加分页窗口2
    tabControl.add(tab2, text='分析')      # 分页窗口2名称
    tabControl.pack(expand=1, fill="both")  # 位置调整
    monty = ttk.LabelFrame(tab1, text='爬取数据')
    monty2 = ttk.LabelFrame(tab2, text='分析数据')#窗口标题
    #monty3 = ttk.LabelFrame(tab1, text='爬取结果')
    #monty3.grid(column=0, row=5, padx=8, pady=4)
    monty.grid(column=0, row=0, padx=8, pady=4)
    monty2.grid(column=0, row=0, padx=8, pady=4)#以表格形式调整位置
    Label(monty,text='商品名称 :').grid(row=0,column=0) # 对Label内容进行 表格式 布局
    Label(monty,text='爬取页数 :').grid(row=0,column=2)
    #Label(monty, text='爬取结果 :').grid(row=2, column=0)
    Label(monty,text='保存文件类型 :').grid(row=1,column=0)
    v1=StringVar()    # 设置变量 . 
    v2=StringVar()
    #v3='kfd'
    e1 = Entry(monty,textvariable=v1)            # 用于储存 输入的内容  
    e2 = Entry(monty,textvariable=v2)
    #e3 = Entry(monty, textvariable=v3)
    e1.grid(row=0,column=1,padx=10,pady=5)      # 进行表格式布局 . 
    e2.grid(row=0,column=3,padx=10,pady=5)
    #e3.grid(row=2, column=2, padx=10, pady=5)
    number =StringVar()
    numberChosen =ttk.Combobox(monty, width=12, textvariable=number)
    numberChosen['values'] = ('Excel表格','txt文件')     # 设置下拉列表的值
    numberChosen.grid(column=1, row=1)      # 设置其在界面中出现的位置  column代表列   row 代表行
    numberChosen.current(0)    # 设置下拉列表默认显示的值，0为 numberChosen['values'] 的下标值
    def fd():
        #按钮‘开始爬取’命令函数
        url=e1.get()        #获取输入的商品名称
        y=e2.get()          #获取输入的爬取页数
        file_save = numberChosen.get()#获取文件保存类型
        try:
            int(y)          #判断输入是否正确
        except:            #警告页面
            messagebox.showwarning(title='警告！', message='输入有误' + '\n'
                                                                     '请重新输入...')
        try:               #调用函数爬取数据
            urlsd(url,y,file_save)
            messagebox.showinfo(title='恭喜！', message='爬虫获取信息成功' + '\n'
                                                                  '现在可以分析啦')
        except:
            messagebox.showwarning(title='警告！', message='爬虫获取信息失败' + '\n'
                                                                  '请重试...')
    Button(monty,text='开始爬取',width=10,command=fd).grid(row=1,column=3,sticky=W,padx=10,pady=5)  # 设置 button 指定 宽度 , 并且 关联 函数 , 使用表格式布局 .

    Button(monty,text='退出',width=10,command=root.quit).grid(row=3,column=3,sticky=E,padx=10,pady=5)#退出程序
    ###############分析框
    n =StringVar()
    Label(monty2,text='分析方法 :').grid(row=0,column=0)
    nChosen =ttk.Combobox(monty2, width=18, textvariable=n)
    nChosen['values'] = ('店家所在地省份分析','商店名称分析','价格区间分析','商品名称分析','销量与商品位置分析')     # 设置下拉列表的值
    nChosen.grid(column=1, row=0)      # 设置其在界面中出现的位置  column代表列   row 代表行
    nChosen.current(0)    # 设置下拉列表默认显示的值，0为 numberChosen['values'] 的下标值
    def gf():           #调用函数分析数据
        sj=nChosen.get()#获取列表内容
        if sj=='店家所在地省份分析':
           excel_pattern()
        elif sj=='商店名称分析':
            picher()
        elif sj=='价格区间分析':
            tiao()
        elif sj=='商品名称分析':
            merchandise_name()
        elif sj=='销量与商品位置分析':
            tiaop()
        
    Button(monty2,text='开始分析',width=10,command=gf).grid(row=0,column=3,sticky=W,padx=10,pady=5)
    Button(monty2, text='退出', width=10, command=root.quit).grid(row=3, column=3, sticky=E, padx=10, pady=5)
    root.mainloop()
    
if __name__ == '__main__':
    main()
    #tiao()
    #excel_pattern()
    #picher()
    #tiaop()
  
  
